package com.spring.cloud.eurekaclientgateway;


import brave.Tracer;
import com.spring.cloud.eurekaclientgateway.filter.RateLimiterFilter;
import com.spring.cloud.eurekaclientgateway.filter.RateLimiterGatewayFilter;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cglib.core.Local;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

@SpringBootApplication
@RestController
@RefreshScope
public class EurekaClientGatewayApplication {




    public static void main(String[] args) {
        SpringApplication.run(EurekaClientGatewayApplication.class, args);
    }


//    //path 路径匹配
//    @Bean
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        return builder.routes() //开启路由配置
//                .route("user",f->f.path("/user/**") //route方法逻辑是一个断言
//                .uri("http://localhost:6001"))  //转发到具体的URI
//                .build();       //创建
//    }

//    @Bean   //before 之后2分钟路由失效
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//
//        ZonedDateTime datetime = LocalDateTime.now()      //获取当前时间
//                .plusMinutes(2)         //2分钟后失效
//                .atZone(ZoneId.systemDefault());  //定义UTC时间
//
//        System.out.println(datetime.toString());
//
//        return builder.routes()
//                .route("/user/**",r->r.before(datetime)     //使用断言
//                .uri("http://localhost:6001"))
//                .build();
//    }

//    @Bean       //after在 时间点之后 生效
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        ZonedDateTime dateTime = LocalDateTime.now()
//                .plusMinutes(1)
//                .atZone(ZoneId.systemDefault());
//        return builder.routes()
//                .route("/user/**",r->r.after(dateTime)
//                .uri("http://localhost:6001"))
//                .build();
//    }


//    @Bean       //两个时间点之间生效 between
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        ZonedDateTime dateTime1 = LocalDateTime.now()
//                .plusMinutes(1)
//                .atZone(ZoneId.systemDefault());
//        ZonedDateTime dateTime2 = LocalDateTime.now()
//                .plusMinutes(2)
//                .atZone(ZoneId.systemDefault());
//        return builder.routes()
//                .route("/user/**",r->r.between(dateTime1,dateTime2)
//                .uri("http://localhost:6001"))
//                .build();
//    }


//    @Bean       //cookie_id 参数匹配 abcd.*的正则表达式
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        return builder.routes()
//                .route("/user/**",r->r.cookie("cookie_id","abcd.*")
//                        .uri("http://localhost:6001"))
//                        .build();
//    }

//    @Bean       //请求头中 参数 符合 id:0-9的数字 一个或多歌
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//
//        String regex = "^[0-9]*$";      //java正则 ^开始  $结束 []范围字符 * 0个或多个
//
//        return builder.routes()
//                .route("/user/**",r->r.header("id",regex)
//                        .uri("http://localhost:6001"))
//                .build();
//    }


//    @Bean       //匹配主机名或域名 符合表达式 host1和host2的规则
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        String host1 = "**.host.com:3001";
//        String host2 = "**.myhost.com:3001";
//
//        return builder.routes()
//                .route("/user/**",r->r.host(host1,host2)
//                        .uri("http://localhost:6001"))
//                .build();
//    }

//    @Bean       //匹配请求方式为GET ,POST
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        return builder.routes()
//                .route("/user/**",r->r.method(HttpMethod.GET,HttpMethod.POST)
//                        .uri("http://localhost:6001"))
//                .build();
//    }

//    @Bean       //请求必须符合要求的参数才能通过请求
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//
//        String regex = "^[0-9]*$";
//
//        return builder.routes()
//                .route("user",r->r.query("id",regex).uri("http://localhost:6001")).build();
//    }

//    @Bean       //请求地址符合192.168.31.0/0  -- 192.168.31.0/32范围内的  http://192.168.31.26:3001/user/info/1 这样的地址
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//
//        //192.168.31.0 为IP地址,0为子网掩码
//        String addr1 = "192.168.31.0/0";
//        //192.168.31.0 为IP地址,32为子网掩码
//        String addr2 = "192.168.31.0/32";
//
//        return builder.routes()
//                .route("user",r->r.remoteAddr(addr1,addr1).uri("http://localhost:6001")).build();
//    }

//    @Bean       //按权重分配 访问哪个微服务
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//
//       String groupName = "user_info";
//       String path = "/user/info/{id}";
//
//        return builder.routes()
//                //id  path请求的路径
//                .route("user_info_v1",r->r.path(path)
//                        //and连接语义
//                        .and()
//                        //权重 groupName 代表一组属于一个功能的微服务, 80代表权重值越大访问的几率越高
//                        .weight(groupName,80)
//                        //微服务urI
//                        .uri("http://localhost:6001"))
//                .route("user_info_v2",r->r.path(path)
//                        .and()
//                        .weight(groupName,20)
//                        .uri("http://localhost:6001"))
//                .build();
//    }


        //过滤器的使用
//    @Bean
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        return builder.routes() //开启路由配置
//                .route("user",r->r.path("/user/**") //route方法逻辑是一个断言

                        //通过增加请求头过滤器添加请求头参数
//                        .filters(f->f.addRequestHeader("id","1"))
                        //通过增加请求参数过滤器添加请求参数
//                        .filters(f->f.addRequestParameter("id","1"))
                        //通过增加响应头参数过滤器添加响应参数
//                        .filters(f->f.addResponseHeader("token","a123456789"))
                        //重试2次(最多尝试路由3次,其中2次是重试)源请求算一次
//                        .filters(f->f.retry(2))
                        //重试详细配置
//                        .filters(f->f.retry(retryConfig -> {
////                            //重试次数为2
////                            retryConfig.setRetries(2);
////                            //接受HTTP的请求方法,限制范围为GET,POST,PUT
////                            retryConfig.setMethods(HttpMethod.GET,HttpMethod.POST,HttpMethod.PUT);
////                            //限制重试的响应码为服务器错误(500)和坏请求(400)
////                            retryConfig.setStatuses(HttpStatus.INTERNAL_SERVER_ERROR,HttpStatus.BAD_REQUEST);
////                            //限制重试的系列为服务器错误
////                            retryConfig.setSeries(HttpStatus.Series.SERVER_ERROR);
////                        }))

                        //过滤器 降级服务
//                        .filters(f->f.hystrix(config -> {
//                            //Hystrix命令名
//                            config.setName("hystrix-cmd");
//                            //降级跳转的URI
//                            config.setFallbackUri("forward:/gateway/fallback");
//                            //设置hystrix Setter 的参数
//                            config.setSetter();
//                        }))

                        //限速器RequestRateLimiter的实现类是RedisRateLimiter不使用代码 使用yml配置方便


                        //通过StripPrefix URI的前缀 进行删除1个
//                        .filters(f->f.stripPrefix(1))

                        //重写请求路径 过滤器
//                        .filters(f->f.rewritePath("/u/(?<segment>.*)","/$\\{segment}"))

                        //设置状态(setStatus)过滤器工厂设置状态
//                        .filters(f->f.setStatus(HttpStatus.BAD_REQUEST.value()))


//                .uri("http://localhost:6001"))  //转发到具体的URI
//                .build();       //创建
//    }


//    @Bean   //针对 RequestRateLimiter限速器对 用户编号进行请求限制配置的用户编号id
//    public KeyResolver pathKeyResolver(){
//        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userid"));
//    }


    //resilience4j 自定义限速器
    private RateLimiterRegistry rateLimiterRegistry;
    private RateLimiterConfig rateLimiterConfig;

    //resilience4j 自定义限速器 的配置
    @Bean(name = "rateLimiterConfig")
    public RateLimiterConfig initRateLimiterConfig(){
        if(rateLimiterConfig == null){
            rateLimiterConfig = RateLimiterConfig.custom()
                    //访问次数
                    .limitForPeriod(3)
                    //超时时间 millis 微秒
                    .timeoutDuration(Duration.ofMillis(10))
                    //时间戳 millis 微秒
                    .limitRefreshPeriod(Duration.ofMillis(5000))
                    .build();
        }
        return rateLimiterConfig;
    }

    //resilience4j 自定义限速器 注册机
    @Bean(name = "rateLimiterRegistry")
    public RateLimiterRegistry initRateLimiterRegistry(){
        if(rateLimiterConfig == null){
            initRateLimiterConfig();
        }
        if(rateLimiterRegistry == null){
            rateLimiterRegistry = RateLimiterRegistry.of(rateLimiterConfig);
            rateLimiterRegistry.rateLimiter("user");
        }
        return rateLimiterRegistry;
    }

//    @Autowired
//    private RateLimiterFilter rateLimiterFilter;

    @Autowired
    private RateLimiterGatewayFilter rateLimiterGatewayFilter;



    @Bean       //手动自定义的局部过滤器  也不同时也包含全剧过滤器 可用可不用
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){


        return builder.routes()
                .route("user-service",r->r.path("/user/**")
//                        .filters(f->f.filter(rateLimiterFilter.customGatewayFilter()))
                        //使用接口实现类方式的局部过滤器
                        .filters(f->f.filter(rateLimiterGatewayFilter))
                .uri("http://localhost:6001"))
                .build();
    }


    //通过微服务ID 去进行路由
//    @Bean
//    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//        return builder.routes()
//                .route("user-service",r->r.path("/user/**")
//                 //通过微服务ID 去转发URI 基于服务发现方式 并不是上面定死的http://localhost:6001
//                .uri("lb://eureka-client-user"))
//                .build();
//    }

    @Value("${version.message}")
    private String message;

    @GetMapping("/version/message")
    public String versionMessage(){
        return message;
    }


}
